package com.andaily.service.impl;

import com.andaily.domain.dto.user.ForgotPasswordDTO;
import com.andaily.domain.dto.user.RegisterUserDTO;
import com.andaily.domain.dto.user.UserFormDTO;
import com.andaily.domain.shared.PasswordHandler;
import com.andaily.domain.shared.security.SecurityUtils;
import com.andaily.domain.user.AccountSetting;
import com.andaily.domain.user.User;
import com.andaily.domain.user.UserRepository;
import com.andaily.domain.user.UserSetting;
import com.andaily.infrastructure.support.LogHelper;
import com.andaily.service.MailService;
import com.andaily.service.UserService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Shengzhao Li
 */
public class UserServiceImpl implements UserService {

    private static LogHelper log = LogHelper.create(UserServiceImpl.class);

    private UserRepository userRepository;
    private MailService mailService;

    @Override
    public void saveRegisterUser(RegisterUserDTO registerUserDTO) {
        log.info("Call saveRegisterUser, registerUserDTO = " + registerUserDTO);
        User user = registerUserDTO.toRegisterUser();
        userRepository.saveUser(user);
        //save default UserSetting
        saveDefaultUserSetting(user);
        //send mail
        mailService.sendRegisterUserMail(user);
    }

    private void saveDefaultUserSetting(User user) {
        User createdUser = userRepository.findByGuid(user.guid());
        UserSetting userSetting = new UserSetting(createdUser);
        userRepository.saveUserSetting(userSetting);
    }

    @Override
    public String loadUserGuidByEmail(String email) {
        return userRepository.findUserGuidByEmail(email);
    }

    @Override
    public boolean activeRegisterUser(String code) {
        log.debug("Active user by code: " + code);
        User user = userRepository.findArchivedUser(code);
        if (user == null || !user.archived()) {
            return false;
        }
        userRepository.activeUser(user.guid());
        return true;
    }

    @Override
    public void forgotPassword(ForgotPasswordDTO forgotPasswordDTO) {
        String email = forgotPasswordDTO.getEmail();
        User user = userRepository.findByEmail(email);
        if (user != null) {
            String newPass = user.changeNewPassword();
            userRepository.updatePassword(user);
            mailService.sendForgotPasswordMail(user, newPass);
        } else {
            log.debug("Forgot password failed, not found any user by email: " + email);
        }
    }

    @Override
    public User currentUser() {
        String guid = SecurityUtils.currentUserGuid();
        return userRepository.findByGuid(guid);
    }

    /**
     * If not found user setting from DB, will create a default setting and return it.
     *
     * @param userGuid userGuid
     * @return UserSetting
     */
    @Override
    public UserSetting loadUserSettingByUserGuid(String userGuid) {
        log.debug("Load UserSetting by userGuid = " + userGuid);
        UserSetting userSetting = userRepository.findUserSettingByUserGuid(userGuid);

        if (userSetting == null) {
            User user = userRepository.findByGuid(userGuid);
            userSetting = new UserSetting(user);
            log.debug("The UserSetting is null, create a default UserSetting [" + userSetting + "]");
        }

        return userSetting;
    }

    @Override
    public void updateAccountSettingByUserGuid(AccountSetting accountSetting, String userGuid) {
        log.debug("Update AccountSetting by userGuid = " + userGuid);
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("setting", accountSetting);
        params.put("userGuid", userGuid);
        userRepository.updateAccountSettingByUserGuid(params);
    }

    @Override
    public UserFormDTO loadUserFormDTO() {
        String userGuid = SecurityUtils.currentUserGuid();
        log.debug("Load UserFormDTO by current user[" + userGuid + "]");
        User user = userRepository.findByGuid(userGuid);
        return new UserFormDTO(user);
    }

    @Override
    public boolean updateUserSetting(UserFormDTO userFormDTO) {
        log.debug("Update User setting by " + userFormDTO);
        String userGuid = SecurityUtils.currentUserGuid();
        Map<String, Object> updateMap = userFormDTO.updateMap(userGuid);
        log.debug("Update map: " + updateMap);
        userRepository.updateUser(updateMap);
        return true;
    }

    @Override
    public boolean checkCurrentUserPassword(String password) {
        log.debug("Check current user password: " + password);
        String userGuid = SecurityUtils.currentUserGuid();
        String encryptPass = PasswordHandler.encryptPassword(password);
        String myPass = userRepository.findMyPassword(userGuid);
        boolean equals = myPass.equals(encryptPass);
        log.debug("Check result: " + equals);
        return equals;
    }

    @Override
    public boolean uniqueCellphone(String cellPhone) {
        String userGuid = userRepository.findUserGuidByCellphone(cellPhone);
        return StringUtils.isEmpty(userGuid);
    }

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void setMailService(MailService mailService) {
        this.mailService = mailService;
    }
}
